# coding=utf-8
# author=haishan09@gmail.com
import json
import copy
from collections import defaultdict


class BaseConfig(object):

    templ = []

    def __init__(self, name=None, label=None, config=None, initial=None):
        self.name = name
        self.label = label
        if initial and (isinstance(initial, str) or isinstance(initial, unicode)):
            self.initial = json.loads(initial)
        else:
            self.initial = initial
        self.config = config or copy.deepcopy(self.templ)

    @property
    def names(self):
        return [property.get('name') for property in self.config]

    @property
    def labels(self):
        return [property.get('label') for property in self.config]

    @property
    def defaults(self):
        return [property.get('default') for property in self.config]

    @property
    def widgets_from_config(self):
        return [self.get_widget(property) for property in self.config]

    def parse(self, content):
        pass


class ConfigAlreadyRegistered(Exception):
    pass


class ConfigNotRegistered(Exception):
    pass


class ConfigManager(object):

    def __init__(self):
        self._registry = defaultdict(lambda :defaultdict(lambda: None))

    def register(self, config_module, config_type, config_cls):
        if self._registry[config_module][config_type]:
            raise ConfigAlreadyRegistered(
                'The {0}\' config is already registered'.format(config_type))
        self._registry[config_module][config_type] = config_cls

    def unregister(self, config_module, config_type):
        if not self._registry[config_module][config_type]:
            raise ConfigNotRegistered(
                'The {0}\' config is not registered'.format(config_type))
        self._registry[config_module][config_type] = None

    def get_config(self, config_module, config_type):
        return self._registry[config_module][config_type] or BaseConfig


configmanager = ConfigManager()

def config_register(config_module, config_type):
    def _config_register_wrapper(config_cls):
        configmanager.register(config_module, config_type, config_cls)
        return config_cls
    return _config_register_wrapper

